package com.qf.listener;

import com.rabbitmq.client.Channel;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

/**
 *  防止消费被重复消费
 * @author lixu
 */
@Component
public class MessageRetryCustomListener {

/*    @Autowired
    private RedisTemplate redisTemplate;*/
    @Autowired
    private StringRedisTemplate stringRedisTemplate;//值类型 String类型

    /**
     * 防止消费被重复消费  消费者2
     *  Redis
     *    id无
     *    id:0   key:id  value:0
     *    id:1   key:id  value:1
     *
     *    id：永远唯一的ID
     *      雪花算法
     *      UUID
     */
    @RabbitListener(queues = "queue_c1")
    public void rQ1(String msg, Message message, Channel channel) throws Exception{

        String id = (String) message.getMessageProperties().getHeaders().get("spring_returned_message_correlation");
        //1:假设有ID
        //String id = "";//97186377-d8ea-43a6-9f67-21aab56395cb
        //2:判断当前消息是否正在被消费
        message.getMessageProperties().getDeliveryTag();// 100万 在队列  标识

        //要用一行代码 直接判断是不是被消费 如果没有被消费马上占用id 不允许其它消费者所有消费了


        // setnx :  key:id在吗？ 不在 set  在 ：啥也不干
        Boolean isFlag = stringRedisTemplate.opsForValue().setIfAbsent(id, "0");//Redis:单线程
        //发生网络波动
        if(isFlag){
            //未消费 并上锁了  由我来消费
            System.out.println("====消费了===");
            //消费完成
            stringRedisTemplate.opsForValue().set(id,"1");
            channel.basicAck(message.getMessageProperties().getDeliveryTag(),false);
        }else{
            //被消费了  但是我不知道是消费到什么程度了  0：刚刚在消费  1：消费完成了

            String value = stringRedisTemplate.opsForValue().get(id);

            if(!StringUtils.isEmpty(value) && "0".equals(value)){
                //啥也不干
            }else{
                //帮它应答
                channel.basicAck(message.getMessageProperties().getDeliveryTag(),false);
            }
        }
    }

}
